import React, { useEffect, useState } from 'react';
import { Modal, Form, Input, Select, message } from 'antd';
import PropTypes from 'prop-types';
import cn from 'classnames';
import _ from 'lodash';
import TagSelect from '@components/tag-select';
import OrgCascader from '@components/org-cascader';
import WeightRate from '@components/weight-rate';
import { addAsset, updateAsset } from '@api/asset';
import validatorCreator from '@util/validator-creator';
import { IP_RE, IP_V6, URL_RE } from '@util/constants';
import CheckboxSelect from '@components/checkbox-select';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { bindActionCreators } from 'redux';
import { actions as assetManageActions } from '../../reducer';
import SelectWithCascader from '@components/select-with-cascader';
import './index.less';

const SelectOption = Select.Option;
const { Option } = Select;

const parseDomain = (url = '') => {
  const parsed = url.match(/^(http:\/\/|https:\/\/)(.*)$/);
  if (!parsed) {
    return ['', url];
  }
  return [parsed[1], parsed[2]];
};

function InputWithPrefix(props) {
  const { value = [], prefixOptions, prefixProps, onChange, inputProps } = props;
  const prefix = (
    <Select
      {...prefixProps}
      value={value[0]}
      onChange={perfixValue => onChange([perfixValue, value[1]])}
    >
      {prefixOptions.map(item => (
        <SelectOption value={item.key} key={item.key}>
          {item.name}
        </SelectOption>
      ))}
    </Select>
  );
  return (
    <Input
      {...inputProps}
      addonBefore={prefix}
      value={value[1]}
      onChange={e => {
        onChange([value[0], e.target.value]);
      }}
    />
  );
}
InputWithPrefix.propTypes = {
  value: PropTypes.array,
  prefixOptions: PropTypes.array,
  prefixProps: PropTypes.array,
  onChange: PropTypes.func,
  inputProps: PropTypes.object
};

function SelectWithNew(props) {
  const { placeholder, options: initOptions = [], value, onChange } = props;
  const [options, setOptions] = useState(initOptions);

  useEffect(() => {
    setOptions(initOptions);
  }, [initOptions]);

  return (
    <Select
      value={value}
      onChange={onChange}
      placeholder={placeholder}
      showSearch
      onSearch={search => {
        if (search) {
          const id = `new_${search}`;
          setOptions(
            options.filter(i => !/^new_/.test(i._id)).concat({ name: search, _id: id }),
            () => onChange(value.concat(id))
          );
        }
      }}
    >
      {options.map(option => (
        <Select.Option value={option._id} key={option._id}>
          {option.name}
        </Select.Option>
      ))}
    </Select>
  );
}
SelectWithNew.propTypes = {
  placeholder: PropTypes.string,
  options: PropTypes.array,
  value: PropTypes.string,
  onChange: PropTypes.func
};

class AssetSettingModal extends React.Component {
  static propTypes = {
    visible: PropTypes.bool,
    form: PropTypes.object,
    site: PropTypes.object,
    setState: PropTypes.func,
    requestLoadAssetStatsCallback: PropTypes.func,
    loadAssetIndustry: PropTypes.func,
    loadAssets: PropTypes.func,
    loadAssetCategoryList: PropTypes.func,
    organizationTree: PropTypes.array,
    onOrgPopupVisibleChange: PropTypes.func,
    customAttributeList: PropTypes.array,
    assetCategoryTree: PropTypes.array,
    allIndustries: PropTypes.array,
    areaList: PropTypes.array,
    staffList: PropTypes.array,
    role: PropTypes.string,
    useCallbackGetCert: PropTypes.func
  };

  constructor(props) {
    super(props);
    this.state = {
      svaing: false,
      needAtLeastOneError: false
    };
  }

  static getDerivedStateFromProps(nextProps) {
    if (!nextProps.visible) {
      return {
        svaing: false
      };
    }
  }

  componentDidUpdate(prevProps) {
    if (!prevProps.visible && this.props.visible) {
      const {
        form: { setFieldsValue, resetFields },
        site
      } = this.props;
      if (site && site._id) {
        if (site.url) {
          site.url = parseDomain(site.url);
        }
        setFieldsValue(site);
      } else {
        resetFields();
        setFieldsValue({
          weight: 1
        });
      }
    }
  }

  onSave = () => {
    const {
      form: { validateFieldsAndScroll },
      customAttributeList,
      setState,
      loadAssets,
      loadAssetCategoryList,
      requestLoadAssetStatsCallback,
      loadAssetIndustry,
      useCallbackGetCert
    } = this.props;
    let customAttributeNameMapId = _.reduce(
      customAttributeList,
      (total, item) => {
        return Object.assign(total, { [item.name]: item._id });
      },
      {}
    );

    validateFieldsAndScroll((errors, values) => {
      if (errors) {
        return;
      }
      // 处理自定义属性
      const customAttributes = [];

      _.forIn(values, (value, key) => {
        if (value && /^CUSTOM_ATTRIBUTE_/.test(key)) {
          const attributeOid = customAttributeNameMapId[key.replace(/^CUSTOM_ATTRIBUTE_/, '')];
          customAttributes.push({
            attributeOid,
            value: [].concat(value)
          });
          delete values[key];
        }
      });
      if (!_.isEmpty(customAttributes)) {
        values.customAttributes = customAttributes;
      }

      // 处理URL和前缀
      const [prefix, url] = values.url || [];
      delete values.url;
      if (url && !/^(http:\/\/|https:\/\/)/.test(url)) {
        values.url = (prefix + url).trim();
      } else if (url) {
        values.url = url.trim();
      }

      values.organization = _.last(_.get(values, 'organization', []));

      this.setState({ svaing: true });
      let successInfo, errorInfo, action;
      if (values._id) {
        // eslint-disable-next-line
        values.site_id = id;
        successInfo = '修改资产成功';
        errorInfo = '修改资产失败';
        action = updateAsset;
      } else {
        successInfo = '添加资产成功';
        errorInfo = '添加资产失败';
        action = addAsset;
      }
      action(values)
        .then(() => {
          message.success(successInfo);
          setState({
            assetSettingModalVisible: false
          });
          loadAssets();
          loadAssetCategoryList();
          requestLoadAssetStatsCallback();
          loadAssetIndustry();
          useCallbackGetCert();
        })
        .catch(({ type, message: messageString }) => {
          if (type === 'parsed') {
            errorInfo = messageString;
          }
          message.warning(errorInfo);
        })
        .finally(() => {
          this.setState({
            svaing: false,
            searchKeyWordDataType: ''
          });
        });
    });
  };
  rendercustomAttributeList = () => {
    const {
      form: { getFieldDecorator },
      customAttributeList = []
    } = this.props;
    return customAttributeList.map(item => {
      return (
        <Form.Item key={item.name} label={item.name}>
          {getFieldDecorator(`CUSTOM_ATTRIBUTE_${item.name}`)(
            item.type === 'string' ? (
              <Input placeholder="请输入中文、英文、特殊字符或者数字，不超过32个字符" />
            ) : item.type === 'single' ? (
              <Select
                allowClear
                dropdownClassName="add-asset-modal-url-prefix"
                style={{ width: '100%' }}
                placeholder="请选择"
              >
                {_.get(item, 'options', []).map(optionItem => (
                  <SelectOption key={optionItem} value={optionItem}>
                    {optionItem}
                  </SelectOption>
                ))}
              </Select>
            ) : item.type === 'multiple' ? (
              <CheckboxSelect
                boxHeight={100}
                className="plugins"
                placeholder="请输入选项名称进行搜索"
                options={_.get(item, 'options', []).map(item => {
                  return {
                    key: item,
                    value: item
                  };
                })}
                optionKey="key"
                namePath="value"
                allButton={false}
              />
            ) : null
          )}
        </Form.Item>
      );
    });
  };

  setDataType = value => {
    this.setState({
      searchKeyWordDataType: value
    });
  };

  render() {
    const {
      visible = false,
      organizationTree,
      form: { getFieldDecorator, getFieldsValue },
      onOrgPopupVisibleChange,
      role,
      staffList = [],
      assetCategoryTree = [],
      allIndustries = [],
      setState
    } = this.props;

    const { svaing, searchKeyWordDataType } = this.state;

    return (
      <div className="aml-c-add-asset-modal">
        <Modal
          maskClosable={false}
          className={cn('add-asset-modal', 'no-header-bottom-lines', 'bottom-center', 'padding-24')}
          title="添加资产"
          visible={visible}
          onCancel={() => setState({ assetSettingModalVisible: false })}
          onOk={this.onSave}
          confirmLoading={svaing}
          width={532}
          okButtonProps={{ className: 'button-forwards' }}
        >
          <div className="content">
            <Form colon={false} labelAlign="left" labelCol={{ span: 4 }} wrapperCol={{ span: 20 }}>
              <Form.Item hidden>{getFieldDecorator('_id')(<Input />)}</Form.Item>
              <Form.Item label="资产名称">
                {getFieldDecorator('name', {
                  rules: [
                    {
                      validator: (rules, value = '', callback) => {
                        if (value.length > 32) {
                          return callback('资产名称不能超过32个字符');
                        }
                        return callback();
                      }
                    }
                  ]
                })(<Input placeholder="如：公司官网" />)}
              </Form.Item>
              <Form.Item label="URL">
                {getFieldDecorator('url', {
                  rules: [
                    {
                      validator: (rules, value = [], callback) => {
                        if (value[1] && !URL_RE.test(value[1])) {
                          return callback('请输入正确格式的URL');
                        }
                        return callback();
                      }
                    }
                  ],
                  initialValue: ['http://', '']
                })(
                  <InputWithPrefix
                    prefixOptions={[
                      { key: 'http://', name: 'http://' },
                      { key: 'https://', name: 'https://' }
                    ]}
                    prefixProps={{
                      dropdownClassName: 'add-asset-modal-url-prefix'
                    }}
                    inputProps={{
                      className: 'url-wrapper',
                      placeholder: '如：www.test.com/page(包含协议、端口)'
                    }}
                  />
                )}
              </Form.Item>
              <Form.Item label="IP">
                {getFieldDecorator('ip', {
                  rules: [
                    {
                      validator: (rules, value = '', callback) => {
                        if (value && !(IP_RE.test(value) || IP_V6.test(value))) {
                          return callback('请输入正确格式的IP');
                        }
                        const { ip, url, name } = getFieldsValue();
                        if (!ip && !_.get(url, 1) && !name) {
                          return callback('资产名称、URL、IP三个字段中需要至少有一个不为空');
                        }
                        return callback();
                      }
                    }
                  ]
                })(<Input placeholder="如：10.0.0.1" />)}
              </Form.Item>
              <Form.Item label="资产分类">
                {getFieldDecorator('assetCategories')(
                  <SelectWithCascader
                    options={assetCategoryTree}
                    placeholder="请选择资产分类"
                    fieldNames={{ label: 'name', value: '_id', children: 'children' }}
                  />
                )}
              </Form.Item>
              <Form.Item label="所属部门">
                {getFieldDecorator('organization')(
                  <OrgCascader
                    onOrgPopupVisibleChange={onOrgPopupVisibleChange}
                    options={organizationTree}
                  />
                )}
              </Form.Item>
              <Form.Item label="管理员">
                {getFieldDecorator('staffOid')(
                  <Select
                    placeholder="请选择管理员"
                    showSearch
                    allowClear
                    filterOption={(input, option) => {
                      return _.includes(
                        _.toLower(_.get(option, 'props.children', '')),
                        _.toLower(input)
                      );
                    }}
                  >
                    {_.map(staffList, staff => (
                      <Select.Option key={staff._id}>
                        {[staff.nickname, staff.email, staff.telephone].filter(Boolean).join('/')}
                      </Select.Option>
                    ))}
                  </Select>
                )}
              </Form.Item>
              <Form.Item label="资产权重">
                {getFieldDecorator('weight', {
                  rules: [
                    {
                      validator: validatorCreator('权重', {
                        required: true
                      })
                    }
                  ],
                  initialValue: 1
                })(<WeightRate />)}
              </Form.Item>
              <Form.Item label="标签">{getFieldDecorator('tag_oids')(<TagSelect />)}</Form.Item>
              <Form.Item label="行业">
                {getFieldDecorator('industry')(
                  <Select
                    style={{ width: '100%' }}
                    showSearch
                    onSearch={value => this.setDataType(value)}
                    placeholder="请输入行业"
                    filterOption={(input, option) => {
                      if (option && option.props && option.props.title) {
                        return (
                          option.props.title === input || option.props.title.indexOf(input) !== -1
                        );
                      } else {
                        return true;
                      }
                    }}
                  >
                    {searchKeyWordDataType &&
                    _.findIndex(allIndustries, ['name', searchKeyWordDataType]) === -1 ? (
                      <Option value={searchKeyWordDataType}>
                        {searchKeyWordDataType}
                        <span style={{ color: 'red' }}>（新增）</span>
                      </Option>
                    ) : (
                      ''
                    )}
                    {allIndustries.map(item => {
                      return (
                        <Option key={item._id} value={item._id} title={item.name}>
                          {item.name}
                        </Option>
                      );
                    })}
                  </Select>
                )}
              </Form.Item>
              {this.rendercustomAttributeList()}
              {role === '安全管理员' ? (
                <Link
                  to="/asset-config/attribute-config"
                  style={{ marginLeft: '76px' }}
                  target="_blank"
                >
                  进行资产属性配置
                </Link>
              ) : (
                <p style={{ marginLeft: '76px', color: '#0b6fd6' }}>可联系管理员增加更多资产属性</p>
              )}
            </Form>
          </div>
        </Modal>
      </div>
    );
  }
}

const mapStateToProps = state => {
  return {
    role: _.get(state, 'auth.user.role', ''),
    organizationTree: _.get(state, 'assetManage.organizationTree', []),
    customAttributeList: _.get(state, 'assetManage.customAttributeList', []),
    assetCategoryTree: _.get(state, 'assetManage.assetCategoryTree', []),
    areaList: _.get(state, 'assetManage.areaList', []),
    allIndustries: _.get(state, 'assetManage.allIndustries', []),
    staffList: _.get(state, 'assetManage.staffList', []),
    site: _.get(state, 'assetManage.currentEditSite', {}),
    visible: _.get(state, 'assetManage.assetSettingModalVisible', {})
  };
};

const mapDispatchToProps = dispatch => {
  return {
    ...bindActionCreators(assetManageActions, dispatch)
  };
};
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Form.create()(AssetSettingModal));
